# -*- coding: UTF-8 -*-
import json
import os
import psutil
import time
from PySide6.QtGui import QFont, QPixmap
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel, QHBoxLayout, QProgressBar, QSizePolicy, QGraphicsView, QSizeGrip
from PySide6.QtCore import Qt, QTimer, QUrl, QPropertyAnimation
from PySide6.QtWebEngineWidgets import QWebEngineView
from pyecharts.charts import Pie, Grid, Liquid, Bar
import pyecharts.options as opts
from pyecharts.commons.utils import JsCode
from Icon import icons
from PySide6.QtCore import QThread, Signal
import re
from Netconfig.base_window import BaseWindow


async def get_cpu_usage():
    return psutil.cpu_percent(interval=1) / 100


async def get_memory_usage():
    return psutil.virtual_memory().percent / 100


class DataUpdater(QThread):
    data_updated = Signal(float, float)

    def run(self):
        while True:
            cpu_usage = get_cpu_usage()
            memory_usage = get_memory_usage()
            self.data_updated.emit(cpu_usage, memory_usage)
            self.msleep(30000)  # 每秒更新一次


class HomeWindow(BaseWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.layout = QVBoxLayout(self.central_widget)

        self.labels = []
        self.progress_bars = []
        self.icons = []
        for i in range(4):
            label = QLabel()
            label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
            label.setFrameStyle(QLabel.Box | QLabel.Plain)
            label.setStyleSheet("background-color: white; border-radius: 5px; padding: 0px;")
            label.setFont(QFont("微软雅黑", 12))
            label.setWordWrap(True)
            label.setFixedHeight(100)
            label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

            self.labels.append(label)

            label.layout = QHBoxLayout()

            if i != 0:
                progress_bar = QProgressBar()
                progress_bar.setFixedHeight(15)
                progress_bar.setFixedWidth(185)
                progress_bar.setFormat("%p%")
                progress_bar.setTextVisible(True)
                progress_bar.setStyleSheet("""
                    QProgressBar {
                        border: 1px solid #E0E0E0;
                        border-radius: 7px;
                        background-color: #F5F5F5;
                        text-align: center;
                        color: black;
                    }
                    QProgressBar::chunk {
                        background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0,
                            stop:0 #4CAF50, stop:1 #81C784);
                        border-radius: 6px;
                    }
                """)
                progress_bar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
                self.progress_bars.append(progress_bar)
                label.layout.addWidget(progress_bar, 0, Qt.AlignBottom)

            icon = QLabel()
            icon.setFixedSize(48, 48)
            self.icons.append(icon)

            label.layout.addWidget(icon, 0, Qt.AlignRight)
            label.layout.setContentsMargins(10, 0, 10, 5)
            label.setLayout(label.layout)

        self.layout.setDirection(QVBoxLayout.TopToBottom)

        self.top_layout = QHBoxLayout()
        self.layout.addLayout(self.top_layout)

        for label in self.labels:
            self.top_layout.addWidget(label)
            self.top_layout.addSpacing(6)  # 新增间隔 5px 的空间

        self.top_layout.setSpacing(0)
        # self.layout.setContentsMargins(0, 0, 0, 0)

        self.devices = load_devices()
        self.update_labels()

        self.timer = QTimer()
        self.timer.timeout.connect(self.refresh_data)
        self.timer.start(30000)

        self.web_view = QWebEngineView()
        file_path = os.path.abspath("./device_config/config_file/device_statistics.html")
        self.web_view.setUrl(QUrl.fromLocalFile(file_path))
        self.layout.addWidget(self.web_view)
        self.web_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.devices = load_devices()  # 这里依然从数据库加载设备
        self.update_labels()

        # 定时器启动
        self.timer.start(30000)
        self.cpu_memory_web_view = QWebEngineView()
        self.cpu_memory_web_view.setUrl(QUrl.fromLocalFile("/device_config/config_file/cpu_memory_usage.html"))
        self.layout.addWidget(self.cpu_memory_web_view)
        self.web_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.chart_layout = QHBoxLayout()
        self.chart_layout.addWidget(self.web_view)
        self.chart_layout.addWidget(self.cpu_memory_web_view)
        self.layout.addLayout(self.chart_layout)

        # 添加设备使用情况柱状图的 QWebEngineView
        self.usage_web_view = QWebEngineView()
        self.layout.addWidget(self.usage_web_view)
        self.usage_web_view.setFixedHeight(320)
        self.update_usage_chart()

        # 添加大小调整控件
        self._size_grip = QSizeGrip(self)
        self._size_grip.setFixedSize(20, 20)
        
        # 在布局末尾添加一个水平布局来放置 size grip
        bottom_layout = QHBoxLayout()
        bottom_layout.addStretch()  # 添加弹性空间
        bottom_layout.addWidget(self._size_grip)  # 添加大小调整控件
        self.layout.addLayout(bottom_layout)

    def update_labels(self):
        device_counts = self.count_devices()
        online_counts = self.count_online_status()

        self.labels[0].setText(f"设备总数\n{device_counts['设备总数']}台")
        self.labels[1].setText(f"交换机/路由器\n{device_counts['交换机'] + device_counts['路由器']}台")
        self.labels[2].setText(f"安全设备\n{device_counts['安全设备']}台")
        self.labels[3].setText(f"在线设备: {online_counts['在线']}台\n离线设备: {online_counts['离线']}台")

        total_devices = device_counts['设备总数']
        if total_devices > 0:
            self.progress_bars[0].setValue(
                int((device_counts['交换机'] + device_counts['路由器']) / total_devices * 100))
            self.progress_bars[1].setValue(int(device_counts['安全设备'] / total_devices * 100))
            self.progress_bars[2].setValue(int(online_counts['在线'] / total_devices * 100))
        else:
            # 如果没有设备数据，将所有进度条重置为 0
            for progress_bar in self.progress_bars:
                progress_bar.setValue(0)

        self.icons[0].setPixmap(self.convert_hex_to_pixmap(icons.DEVICE_TOTAL_ICON))
        self.icons[1].setPixmap(self.convert_hex_to_pixmap(icons.SWITCH_ICON))
        self.icons[2].setPixmap(self.convert_hex_to_pixmap(icons.SECURITY_DEVICE_ICON))
        self.icons[3].setPixmap(self.convert_hex_to_pixmap(icons.ONLINE_DEVICE_ICON))


    def count_devices(self):
        counts = {"交换机": 0, "路由器": 0, "安全设备": 0}
        for device in self.devices:
            if device["device_type"] == "交换机":
                counts["交换机"] += 1
            elif device["device_type"] == "路由器":
                counts["路由器"] += 1
            else:
                counts["安全设备"] += 1
        counts["设备总数"] = len(self.devices)
        return counts

    def count_online_status(self):
        counts = {"在线": 0, "离线": 0}
        for device in self.devices:
            if device["online"] == "在线":
                counts["在线"] += 1
            else:
                counts["离线"] += 1
        return counts

    def refresh_data(self):
        # 从数据库中获取最新的设备数据
        self.devices = load_devices()  # 更新设备信息
        self.update_labels()
        self.update_pie_chart()
        self.update_usage_chart()  # 也更新使用情况柱状图

        # 获取当前的 CPU 和内存使用情况
        cpu_usage = get_cpu_usage()
        memory_usage = get_memory_usage()
        self.update_cpu_memory_chart(cpu_usage, memory_usage)

    def update_usage_chart(self):
    # 提取 CPU 和 Memory 数据，添加检查以确保数据有效
        cpu_usage = []
        memory_usage = []
        fan_usage = []
        power_usage = []
        temperature_usage = []

        for device in self.devices:
            # 确保 device 是一个字典，并且包含必要的键
            if device and isinstance(device, dict):
                cpu_value = device.get('cpu')
                memory_value = device.get('memory')
                fan_value = device.get('fan')
                power_value = device.get('power')
                temperature_value = device.get('temperature')

                # 检查 CPU 使用率是否为有效数值
                if cpu_value is not None and isinstance(cpu_value, str):
                    try:
                        cpu_float = float(cpu_value.strip('%'))
                        cpu_usage.append(cpu_float)  # 使用浮点数
                    except ValueError:
                        pass  # 处理无效数据

                # 检查内存使用率是否为有效数值
                if memory_value is not None and isinstance(memory_value, str):
                    try:
                        memory_float = float(memory_value.strip('%'))
                        memory_usage.append(memory_float)  # 使用浮点数
                    except ValueError:
                        pass  # 处理无效数据

                # 检查风扇状态是否为有效字符串
                if fan_value is not None and isinstance(fan_value, str):
                    fan_usage.append(fan_value.lower() in ["Abnormal", "NotSupply"])  # 转换为布尔值

                # 检查电源状态是否为有效字符串
                if power_value is not None and isinstance(power_value, str):
                    power_usage.append(power_value.lower() in ["Present"])  # 转换为布尔值

                # 检查温度是否为有效数值
                if temperature_value is not None and isinstance(temperature_value, str):
                    try:
                        temperature_float = float(temperature_value)
                        temperature_usage.append(temperature_float)  # 使用浮点数
                    except ValueError:
                        pass  # 处理无效数据

        # 统计超过50%的设备数量
        cpu_over_50_count = sum(1 for usage in cpu_usage if usage > 50)
        memory_over_50_count = sum(1 for usage in memory_usage if usage > 50)
        fan_over_50_count = sum(1 for usage in fan_usage if usage)  # 布尔值为 True 的计数
        power_over_50_count = sum(1 for usage in power_usage if usage)  # 布尔值为 True 的计数
        temperature_over_50_count = sum(1 for usage in temperature_usage if usage > 50)

        # 创建柱状图，并设置自定义宽和高
        bar = Bar(init_opts=opts.InitOpts(width="820px", height="300px"))  # 设置图表的宽和高
        bar.add_xaxis(["CPU > 50%", "Memory > 50%", "Fan", "Power", "Temperature"])
        bar.add_yaxis("CPU", [cpu_over_50_count, None, None, None, None], label_opts=opts.LabelOpts(is_show=True))
        bar.add_yaxis("Memory", [None, memory_over_50_count, None, None, None], label_opts=opts.LabelOpts(is_show=True))
        bar.add_yaxis("FAN", [None, None, fan_over_50_count, None, None], label_opts=opts.LabelOpts(is_show=True))
        bar.add_yaxis("Power", [None, None, None, power_over_50_count, None], label_opts=opts.LabelOpts(is_show=True))
        bar.add_yaxis("Temperature", [None, None, None, None, temperature_over_50_count], label_opts=opts.LabelOpts(is_show=True))
        bar.set_global_opts(title_opts=opts.TitleOpts(title="设备告警统计"))

        # 自定义模板内容
        template = '''
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8">
                <title>Device Usage Statistics</title>
                <script type="text/javascript" src="echarts.min.js"></script>
            </head>
            <body>
                {my_chart}
            </body>
            </html>
        '''

        # 渲染图表并清理 HTML
        chart_html = bar.render_embed()
        cleaned_chart_html = re.sub(r'<title>.*?</title>', '', chart_html, flags=re.DOTALL)

        # 渲染模板
        rendered_html = template.format(my_chart=cleaned_chart_html)

        # 保存生成的 HTML 文件到 device_usage.html
        with open('./device_config/config_file/device_usage.html', 'w', encoding='utf-8') as f:
            f.write(rendered_html)

        # 重新加载外部 HTML 文件
        self.usage_web_view.setUrl(QUrl.fromLocalFile(os.path.abspath('./device_config/config_file/device_usage.html')))


    def update_pie_chart(self):
        lab, num = generate_pie_chart_data(self.devices)

        c = Pie()
        c.add("", [list(z) for z in zip(lab, num)], radius=["20%", "55%"])
        c.set_global_opts(
            title_opts=opts.TitleOpts(title="设备厂商统计图"),
            legend_opts=opts.LegendOpts(
                orient="vertical",
                pos_top="15%",
                pos_left="-1%",
                item_width=16,
                item_height=12
            ),
        )
        c.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}"))
        c.width = "430px"
        c.height = "242px"

        template = '''
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="utf-8">
            <title>Pie Chart</title>
            <script type="text/javascript" src="echarts.min.js"></script>
        </head>
        <body>
            {my_chart}
        </body>
        </html>
        '''

        chart_html = c.render_embed()
        cleaned_chart_html = re.sub(r'<title>.*?</title>', '', chart_html, flags=re.DOTALL)

        rendered_html = template.format(my_chart=cleaned_chart_html)

        with open("./device_config/config_file/device_statistics.html", "w", encoding="utf-8") as f:
            f.write(rendered_html)

        self.web_view.setUrl(QUrl.fromLocalFile("/device_config/config_file/device_statistics.html"))

        self.data_updater = DataUpdater()
        self.data_updater.data_updated.connect(self.update_cpu_memory_chart)
        self.data_updater.start()

    def update_cpu_memory_chart(self, cpu_usage, memory_usage):
        l1 = (
            Liquid()
            .add("", [cpu_usage], center=["30%", "60%"])
            .set_global_opts(
                title_opts=opts.TitleOpts(title="CPU利用率", pos_top="5%", pos_left="16%")
            )
        )

        l2 = Liquid().add(
            "",
            [memory_usage],
            center=["70%", "60%"],
            label_opts=opts.LabelOpts(
                font_size=30,
                formatter=JsCode(
                    """function (param) {return (Math.floor(param.value * 10000)/100)+'%';}"""
                ),
                position="inside",
            ),
        ).set_global_opts(
            title_opts=opts.TitleOpts(title="内存利用率", pos_top="5%", pos_left="55%")
        )

        grid = Grid(init_opts=opts.InitOpts(width="400px", height="240px"))
        grid.add(l1, grid_opts=opts.GridOpts()).add(l2, grid_opts=opts.GridOpts())

        template = '''
                <!DOCTYPE html>
                <html>
                <head>
                    <meta charset="utf-8">
                    <title>CPU & Memory Usage</title>
                    <script type="text/javascript" src="echarts.min.js"></script>
                    <script type="text/javascript" src="echarts-liquidfill.min.js"></script>
                </head>
                <body>
                    {my_chart}
                </body>
                </html>
                '''

        rendered_html = template.format(my_chart=grid.render_embed())

        with open("./device_config/config_file/cpu_memory_usage.html", "w", encoding="utf-8") as f:
            f.write(rendered_html)

        self.cpu_memory_web_view.setUrl(QUrl.fromLocalFile("/device_config/config_file/cpu_memory_usage.html"))

    def convert_hex_to_pixmap(self, hex_string):
        image_data = bytes.fromhex(hex_string)
        pixmap = QPixmap()
        pixmap.loadFromData(image_data)
        return pixmap

    def setValue(self, value):
        if hasattr(self, 'animation'):
            self.animation.stop()
        
        self.animation = QPropertyAnimation(self, b"value")
        self.animation.setDuration(300)  # 动画持续时间（毫秒）
        self.animation.setStartValue(self.value())
        self.animation.setEndValue(value)
        self.animation.start()

    def resizeEvent(self, event):
        """重写调整大小事件以更新 size grip 位置"""
        super().resizeEvent(event)
        # 更新 size grip 位置到右下角
        self._size_grip.move(
            self.width() - self._size_grip.width(),
            self.height() - self._size_grip.height()
        )


import sqlite3  # 添加SQLite库


def load_devices():
    # 从SQLite数据库中加载设备信息
    devices = []
    try:
        # 连接数据库
        conn = sqlite3.connect('device_config/config_file/device_info.db')  # 数据库路径
        cursor = conn.cursor()

        # 查询设备信息
        cursor.execute("SELECT * FROM deviceinfo")
        rows = cursor.fetchall()

        # 将查询结果转换为字典格式
        for row in rows:
            devices.append({
                'device_type': row[2],
                'vendor': row[1],
                'online': row[12],
                'cpu': row[14],
                'memory': row[15],
                'fan': row[16],
                'power': row[17],
                'temperature': row[18],
            })
    except sqlite3.Error as e:
        print(f"数据库错误: {e}")
    finally:
        if conn:
            conn.close()  # 关闭数据库连接

    return devices


def generate_pie_chart_data(devices):
    if not devices:
        return ["无数据"], [100]

    vendor_count = {}
    for device in devices:
        vendor = device.get("vendor", "未知")
        if vendor in vendor_count:
            vendor_count[vendor] += 1
        else:
            vendor_count[vendor] = 1

    lab = list(vendor_count.keys())
    num = list(vendor_count.values())
    return lab, num


def get_cpu_usage():
    return psutil.cpu_percent(interval=1) / 100


def get_memory_usage():
    memory_usage = psutil.virtual_memory().percent / 100
    return memory_usage
